import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Arrays;
import java.util.Calendar;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
/**	
 * This class ...
 */
public class Roster extends JFrame implements ActionListener
{
   private static final long serialVersionUID = 1L;

   private Container content5;
//   private JLabel statusReq;
//   private JLabel holidayStatus;
   private JTextField date = new JTextField(20);
   private JButton generateWeek = new JButton("Generate a 7 days timetable");
   private JButton back = new JButton("Go back");

   public Roster()
   {
      content5 = getContentPane();
      setTitle("Generate Timetable");
      content5.setLayout(new GridLayout(0, 1));
      content5.add(new JLabel("Start date of the weekly timetable (dd/mm/yyyy)"));
      content5.add(date);
      content5.add(generateWeek);
      generateWeek.addActionListener(this);
      content5.add(back);
      back.addActionListener(this);
      // exit the program in case the window it's closed
      setDefaultCloseOperation(DISPOSE_ON_CLOSE);
      pack();
   }//Roster  
  
   public String name;
   public int number;

   public void actionPerformed(ActionEvent event)
   {
     Date theDate = null;
     if(event.getSource()==generateWeek)
     {
       String x = date.getText();
       
       
       if(x.equals(""))
       {
	 Object[] options = {"OK"};
         JOptionPane.showOptionDialog(null, "Start date can not be empty!",
         "Warning", JOptionPane.DEFAULT_OPTION,
         JOptionPane.WARNING_MESSAGE, null, options, options[0]); 
	 return;
       }

       DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
       Date test_date1 = null;
       try
       {
	 test_date1 = df.parse(x);
       }
       catch(ParseException error)
       {
	 Object[] options = {"OK"};
         JOptionPane.showOptionDialog(null, "The format of Start date or end date is wrong!",
         "Warning", JOptionPane.DEFAULT_OPTION,
         JOptionPane.WARNING_MESSAGE, null, options, options[0]); 
	 return;
       }
       if (!df.format(test_date1).equals(x))
       {
	 Object[] options = {"OK"};
         JOptionPane.showOptionDialog(null, "Start date is invalid day!",
         "Warning", JOptionPane.DEFAULT_OPTION,
         JOptionPane.WARNING_MESSAGE, null, options, options[0]); 
	 return;
       }

       String[] words=date.getText().split("/");

       if(words.length<=3)
       {
	 int day = Integer.parseInt(words[0]);
	 int month = Integer.parseInt(words[1])-1;
	 int year = Integer.parseInt(words[2]);
	 theDate = new GregorianCalendar(year,month,day).getTime();
         Date today_date = (Date)(Calendar.getInstance().getTime().clone());
         if(theDate.before(today_date)){
           Object[] options = {"OK"};
           JOptionPane.showOptionDialog(null, "Please enter a day after today!",
           "Warning", JOptionPane.DEFAULT_OPTION,
           JOptionPane.WARNING_MESSAGE, null, options, options[0]); 
	   return;
	 }
       }//if	
    
///// GUI     
/////////////////////////////////////////////////////////////////////////////////////////////////
///// operation
               
       database.openBusDatabase();
       PrintWriter output = null;
       PrintWriter output1 = null;
       try{
	   output = new PrintWriter(new FileWriter("driverTimeTable.txt"));
           output1 = new PrintWriter(new FileWriter("timeTable.txt"));
	   
       //get the drivers and buses
	   int[] driverIDs = DriverInfo.getDrivers();
	   Driver[] drivers = new Driver[driverIDs.length];
	   
	   int[] busIDs = BusInfo.getBuses();
	   Bus[] buses = new Bus[busIDs.length];
	   
	   for(int i=0;i<driverIDs.length;i++)
	   {
	      drivers[i] = new Driver(driverIDs[i], 
              DriverInfo.getName(driverIDs[i]), DriverInfo.getHoursThisWeek(driverIDs[i]));
	   }//for
	   
	   for(int i=0; i<busIDs.length; i++)
	   {
		   buses[i] = new Bus(busIDs[i],BusInfo.busNumber(busIDs[i]));
	   }

	  //System.out.println("Name "+ drivers[i].name +  " hoursThisWeek:" + drivers[i].hoursThisWeek) ;}
	  //System.out.println("No of services: " + TimetableInfo.getNumberOfServices(66));

	  //for(int i =0;i<serviceTimes.length;i++)
	  //System.out.println("Time " + i + ": " + serviceTimes[i]);

	  //generate Roster for one Week
	  //Date theDate = new Date(113,5,17);

	  for(int count=1;count<=7;count++)
	  {
             allocateHoliday(theDate,drivers);
             //Get the IDs of all the routes within the scope of the pilot IBMS
             int[] busRoutes= BusStopInfo.getRoutes();
             for(int i =0;i<busRoutes.length;i++)
             {  //System.out.println("Route " + i + ": " + busRoutes[i]);
        	 output1.println("Route " + i + ": " + busRoutes[i]);
		     output1.println("\n");
        	 //Get all the services in a route for the given timetable kind.	
        	 //getServices(int route, TimetableInfo.timetableKind kind) 
        	 int[] services = TimetableInfo.getServices(busRoutes[i],TimetableInfo.timetableKind(theDate));
        	 for(int j=0;j<services.length;j++)
        	 {//  System.out.print("[Service no: "+ services[j]); 
                output1.print("[Service no: "+ services[j]);
        	    // Get the service times on a given route today for a particular service.
        	    int[] serviceTimes=TimetableInfo.getServiceTimes(busRoutes[i],theDate,services[j]-services[0]);
        	    int start = serviceTimes[0];
        	    int end = serviceTimes[serviceTimes.length-1];
        	    int theService = services[j];

        	    Arrays.sort(drivers);
        	    Driver.assignNextBestDriver(start, end, drivers, theService, theDate, buses);
        	   // Bus.assignBusToDriver(start, end, busList, theService, theDate)

        	    //  System.out.print(" During time: "+(serviceTimes[serviceTimes.length-1]-serviceTimes[0]));
        	    //  System.out.print("Best driver: "+ bestFit.name + "]: ");
        	    output1.print(" Service Time: ");
                    for(int k=0;k<serviceTimes.length;k++){
		        //System.out.print(" " + serviceTimes[k]);
                	output1.print(" " + serviceTimes[k]);
                    }

        	    for(int m=0;m<drivers.length;m++){
        	      for(int n=0;n<10;n++){
        		if(drivers[m].service[n]==theService){
                           //System.out.println(" driver allocated: "+ drivers[m].name);
                           output1.println(" driver allocated: "+ drivers[m].name);
                	}//if
                      }//for
                    }//for driver
        	    output1.println("");
                    //System.out.println("");

        	 }//for
              }//for routes
              //update Driver dayTimeTable; 
              for(int i =0;i<drivers.length;i++){ 
		  drivers[i].updateDriverTimeTable(theDate);
		  Driver.sortSmallArray(drivers[i].startMin,drivers[i].endMin,drivers[i].service);
	      }

              //go to next day
              theDate.setDate(theDate.getDate()+1);
              
              for(int i = 0; i<buses.length; i++){
            	  buses[i].updateBusTimeTable(theDate);
              }
              Arrays.sort(buses);
	  }//for each day of the week
	  for(int i =0;i<drivers.length;i++)
	  {  
	     if(drivers[i].hoursThisWeek!=0)
	     {  
	      System.out.println("------------------------------------------------------------------------------------");
              output.println("------------------------------------------------------------------------------------");
	      System.out.println(drivers[i].oneWeekTimetable);
              output.println(drivers[i].oneWeekTimetable);
	     } 
	  }
       }//try
       catch (Exception exception)
       {
          System.err.println("can not output to file");
       }//catch
       finally
       {
	 if (output != null)
	 {
            output.close();
	    if (output.checkError())
		System.err.println ("Something went wrong with the output");
	 }// if
	 if (output1 != null)
	 {
            output1.close();
	    if (output1.checkError())
		System.err.println ("Something went wrong with the output");
	 }// if
       }// finally
     }//if reqHoliday
     
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
          
     managerInterface first;
     if(event.getSource() == back)
     {
       dispose();
       first = new managerInterface();
       first.setVisible(true);
     }   
   }//main

   //allocate holidays for the given day
   public static void allocateHoliday(Date theDate, Driver[] drivers)
   {
	int i=0;
	int howManyLeft= drivers.length/7;
	while(howManyLeft>0&&i<drivers.length)
	{
	   if(drivers[i].holidays2<2)
           {
	      drivers[i].holidays2++;
	      DriverInfo.setAvailable(drivers[i].number,theDate,false);
	      howManyLeft--;
	   }
           i++;
	}//while
   }//allocateHoliday
   
}//class
